<?php

namespace web\addons\controller;

use \think\App;
use \think\Config;

class AddonsExecute extends \web\common\controller\Controller {
   
    public function run($module, $controller = null, $action = null, $addon = null) {
        defined('ADDON_NAME') or define('ADDON_NAME', $addon);
        defined('MODULE_NAME') or define('MODULE_NAME', $module);
        defined('CONTROLLER_NAME') or define('CONTROLLER_NAME', $controller);
        defined('ACTION_NAME') or define('ACTION_NAME', $action);


        $this->request->module($module);
        $this->request->controller($controller);
        $this->request->action($action);

        if (!empty($addon) && !empty($controller) && !empty($action)) {
            $_module = $module . '/' . $controller;
            $class = self::controller($addon, $_module);
            if ($class) {
                $vars = $_REQUEST;
                if (is_scalar($vars)) {
                    if (strpos($vars, '=')) {
                        parse_str($vars, $vars);
                    } else {
                        $vars = [$vars];
                    }
                }
                defined('ADDON_PUBLIC') or define('ADDON_PUBLIC', '/static/addons/' . $addon . '/' . $module);
                if (!method_exists($class, $action)) {
                    if (App::$debug)
                        throw new \think\exception\HttpException(404, 'method not exists:' . (new \ReflectionClass($class))->getName() . '->' . $action);
                }
                return App::invokeMethod([$class, $action . Config::get('action_suffix')], $vars);
            } else {
                $this->error('没有指定插件名称，控制器或操作！');
            }
        } else {
            $this->error('没有指定插件名称，控制器或操作！');
        }
    }

    private static function controller($addon, $name, $layer = 'controller', $appendSuffix = false, $empty = '') {
        if (strpos($name, '/')) {
            list($module, $name) = explode('/', $name);
        } else {
            $module = $this->request->module();
        }
        $empty = config('empty_controller');
        $class = self::parseClass($addon, $module, $layer, $name, $appendSuffix);
        if (class_exists($class)) {
            return new $class();
        } elseif ($empty && class_exists($emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix))) {
            return new $emptyClass();
        } else {
            if (App::$debug)
                throw new \Exception('未找到控制器:' . $class);
            else {
                $emptyClass = \think\Loader::parseClass($module, $layer, $empty);
                return new $emptyClass();
            }
        }
    }

    private static function parseClass($addon, $module, $layer, $name, $appendSuffix = false) {
        $name = str_replace(['/', '.'], '\\', $name);
        $array = explode('\\', $name);
        $class = \think\Loader::parseName(array_pop($array), 1) . (App::$suffix || $appendSuffix ? ucfirst($layer) : '');
        return ADDONS_NAMESPACE . '\\' . $addon . '\\' . $module . '\\' . $layer . '\\' . $class;
    }

}
